package com.gexada.simplechat.config;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import redis.embedded.RedisServer;

/**
 * 启动一个内置的 {@code Redis} 服务实例。
 * <p>
 * 只应作为测试使用
 *
 */
@Configuration
public class EmbeddedRedisConfig {

	@Bean
	public static RedisServerBean redisServer() {
		return new RedisServerBean();
	}

	/**
	 * Implements BeanDefinitionRegistryPostProcessor to ensure this Bean is
	 * initialized before any other Beans. Specifically, we want to ensure that
	 * the Redis Server is started before RedisHttpSessionConfiguration attempts
	 * to enable Keyspace notifications.
	 */
	static class RedisServerBean implements InitializingBean, DisposableBean, BeanDefinitionRegistryPostProcessor,
			RedisConnectionProperties {
		private RedisServer redisServer;

		public void afterPropertiesSet() throws Exception {
			Map<String, String> config = new HashMap<String, String>();
			config.put("maxheap", "102400000");
			redisServer = new ConfiguarableRedisServer(config, getPort());
			redisServer.start();
		}

		public void destroy() throws Exception {
			if (redisServer != null) {
				redisServer.stop();
			}
		}

		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		}

		public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		}

		private Integer availablePort;

		public int getPort() throws IOException {
			if (availablePort == null) {
				ServerSocket socket = new ServerSocket(0);
				availablePort = socket.getLocalPort();
				socket.close();
			}
			return availablePort;
		}
	}
}